package com.ifonly.activerecord.tx;

import com.ifonly.activerecord.Db;
import com.ifonly.activerecord.exceptions.ActiveRecordException;
import com.ifonly.mvc.ActionInterceptor;
import com.ifonly.mvc.ActionInvocation;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author <a href="mailto:ifonlymaster@163.com">ifonly</a>
 * @version 1.0 2015-12-22 16:10
 * @since JDK 1.6
 */
public class TxInterceptor extends ActionInterceptor {
    private Db db = Db.getInstance();

    @Override
    public void doIntercept(ActionInvocation iv) {
        Connection conn = db.getThreadLocalConnection();

        if (conn != null) {
            try {
                iv.invoke();
                return ;
            } catch (Exception e) {
                throw new ActiveRecordException(e);
            }
        }

        Boolean autoCommit = null;
        try {
            conn = db.getConnection();
            db.setThreadLocalConnection(conn);

            autoCommit = conn.getAutoCommit();
            if (conn.getTransactionIsolation() < db.getTransactionIsolation()) {
                conn.setTransactionIsolation(db.getTransactionIsolation());
            }
            conn.setAutoCommit(false);
            iv.invoke();
            conn.commit();
            conn.setAutoCommit(autoCommit);
        } catch (Throwable throwable) {
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            throw new RuntimeException(throwable);
        } finally {
            if (conn != null) {
                try {
                    if (autoCommit != null) {
                        conn.setAutoCommit(autoCommit);
                    }
                } catch (SQLException e) {
                    // ignore
                }
            }
            db.closeAndRemoveThreadLocalConnection();
        }
    }


}
